[0x02] NASM汇编 [输出hello world!] |
您所在的位置:网站首页 › 汇编语言hallow world › [0x02] NASM汇编 [输出hello world!] |
nasm官方文档:https://www.nasm.us/xdoc/2.14.03rc2/nasmdoc.pdf 当遇到问题时,可以在文档中查询,文档是英文的,需要一定的英语阅读能力。 下面是一个输出的例子。 ; hello.asm section .data msg db 'hello, world!',0xa len equ $-msg section .text global _start _start: mov rax, 4 mov rbx, 1 mov rcx, msg mov rdx, len int 0x80 mov rax, 1 int 0x80在ubuntu 64位的机器上编译运行: nasm -f elf64 -o hello.o hello.asm ld -o hello hello.o ./hello这个时候会在控制台中看到输出结果hello, world! 程序分析: section是程序段的意思,首先定义了.data数据段,在data数据段中,定义了2个变量msg和len。 .text段中,_start作为程序的入口点,当然可以换成其他的名字。 之后,使用了mov指令,对寄存器rax,rbx,rcx,rdx等赋值,最后执行int 0x80,进行系统调用。 我们可以使用系统调用,就是系统函数。rax保存系统调用号,4是System_write的系统调用号,可以在文件/usr/include/x86_64-linux-gnu/asm/unistd_32.h查看系统调用号。不同的系统位置可能不同。 使用man 2 write查看write的用法,找到write函数的原型: ssize_t write(int fd, const void *buf, size_t count);fd是文件描述符,buf是指向要输出内容的指针,而count是输出的数量,按字节计数。 mov rbx, 1 mov rcx, msg mov rdx, lenrbx,rcx,rdx保存系统调用的参数,即fd=1,buf=msg,count=len 当参数更多时,使用下面的寄存器保存系统调用的参数:rbx,rcx,rdx,rsi,rdi,rbp int 0x80指令进行系统调用。
不过,现在可以使用syscall指令来替换int 0x80,这时候,规则有了变化,rax依然保存系统调用号,而系统调用的参数使用下面的寄存器,用户模式的系统调用依次传递的寄存器为:rdi,rsi,rdx,rcx,r8和r9;而内核接口的系统调用依次传递的寄存器为:rdi,rsi,rdx,r10,r8和r9。这里只有第4个参数不同。我们使用的是用户模式的系统调用,因此,上面的hello.asm代码可以修改为下面这样: ; hello2.asm seciont .data msg db 'hello, world',0xa len equ $-msg section .text global _start _start: mov rax, 1 mov rdi, 1 mov rsi, msg mov rdx, len syscall mov rax, 60 syscall这里发生了一些变化,当使用syscall进行系统调用时,需要使用64位的系统调用号,在文件/usr/include/x86_64-linux-gnu/asm/unistd_64.h查看64位的系统调用号。 write的系统调用号是1,而exit的系统调用号是60. |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |